package com.ebeijia.pay;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.ebeijia.common.CommonCodeDefine;
import com.ebeijia.util.LoggerUtil;
import com.ebeijia.util.MD5;
import com.ebeijia.util.PropertiesUtils;
import com.ebeijia.util.SignUtils;
import com.ebeijia.util.XmlUtils;
import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class PaymentSDK {
	private static Logger logger = LoggerFactory.getLogger(PaymentSDK.class);
	private final static String version = "2.0";
	private final static String charset = "UTF-8";
	private final static String sign_type = "MD5";

	/**
	 * 订单提交
	 * 
	 * @param outTradeNo
	 * @param body
	 * @param attach
	 * @param totalFee
	 * @param mchCreateIp
	 * @param timeStart 
	 * @param timeExpire
	 * @return
	 */
	public static PayResult payInfo(String openId, String outTradeNo, String body,
			String attach, String totalFee, String timeStart, String timeExpire)
			throws Exception {
		PayResult payResult = new PayResult();

		/**
		 * （out_trade_no--
		 * 、body--、attach--附加信息、total_fee--总金额、mch_create_ip--终端IP）必须存在
		 * time_start--订单生成时间、time_expire--订单超时时间[格式都是yyyymmddhhmmss]
		 */
		try {

			SortedMap<String, String> map = new TreeMap<String, String>();// 写入集合的数据是有序的
			Map<String, String> resultMap = new HashMap<String, String>();

			map.put("out_trade_no", outTradeNo);// 商户订单号
			map.put("sub_openid", openId);// 用户openid/
			map.put("body", body);// 商品描述
			map.put("attach", attach);// 附加信息
			map.put("total_fee", totalFee);// 总金额
			map.put("mch_create_ip", "127.0.0.1");// 终端IP
			map.put("time_start", timeStart);// 订单生成时间
			map.put("time_expire", timeExpire);// 订单超时时间
			map.put("service", "pay.weixin.jspay");
			map.put("version", version);
			map.put("charset", charset);
			map.put("sign_type", sign_type);
			map.put("mch_id", PropertiesUtils.getProperties("mch_id"));
			map.put("notify_url", PropertiesUtils.getProperties("notify_url"));
			map.put("callback_url",
					PropertiesUtils.getProperties("callback_url"));
			map.put("nonce_str", String.valueOf(new Date().getTime()));
			Map<String, String> params = SignUtils.paraFilter(map);
			StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
			SignUtils.buildPayParams(buf, params, false);
			String preStr = buf.toString();
			String sign = MD5.sign(preStr,
					"&key=" + PropertiesUtils.getProperties("mch_key"), "utf-8");
			map.put("sign", sign);

			String reqUrl = PropertiesUtils.getProperties("req_url");
			CloseableHttpResponse response = null;
			CloseableHttpClient client = null;
			String res = null;
			try {
				HttpPost httpPost = new HttpPost(reqUrl);
				StringEntity entityParams = new StringEntity(
						XmlUtils.parseXML(map), "utf-8");
				httpPost.setEntity(entityParams);
				httpPost.setHeader("Content-Type",
						"text/xml;charset=ISO-8859-1");
				client = HttpClients.createDefault();
				response = client.execute(httpPost);
				if (response != null && response.getEntity() != null) {
					resultMap = XmlUtils.toMap(
							EntityUtils.toByteArray(response.getEntity()),
							"utf-8");
					res = XmlUtils.toXml(resultMap);
					if (!SignUtils.checkParam(resultMap,
							PropertiesUtils.getProperties("mch_key"))) {
						res = "验证签名不通过";
					} else {
						if ("0".equals(resultMap.get("status"))
								&& "0".equals(resultMap.get("result_code"))) {
							res = "ok";
						}
					}
				} else {
					res = "操作失败";
				}
			} catch (Exception e) {
				res = "系统异常";
				logger.error(
						"================调用支付接口初始化出现异常===================", e);
			} finally {
				if (response != null) {
					response.close();
				}
				if (client != null) {
					client.close();
				}
			}
		
			if ("ok".equals(res)) {
				payResult.setStatus(CommonCodeDefine.ERROR_PAY_SUCCESS.getCode());
				payResult.setTokenId(resultMap.get("token_id"));
			} else {
				payResult.setStatus(CommonCodeDefine.ERROR_PAY_FAIL.getCode());
			}
			logger.info("===============支付初始化返回结果=============：" + resultMap);
			
		} catch (Exception ex) {
			payResult.setStatus(CommonCodeDefine.ERROR_PAY_FAIL.getCode());
			logger.error("================调用支付接口初始化出现异常===================", ex);
			
		}
		return payResult;
	}

	/**
	 * 支付退款接口
	 * 
	 * @param outTradeNo
	 * @param transactionId
	 * @param outRefundNo
	 * @param totalFee
	 * @param refundFee
	 */

	public static String submitRefund(String openId, String outTradeNo,
			String transactionId, String outRefundNo, String totalFee,
			String refundFee, String refundChannel) throws Exception {

		Logger logger = LoggerFactory.getLogger(PaymentSDK.class);
		logger.info("=============================支付退款接口进入=====================");
		SortedMap<String, String> map = new TreeMap<String, String>();
		map.put("out_trade_no", outTradeNo);// 商户订单号
		map.put("transaction_id", transactionId);// 威富通订单号
		map.put("out_refund_no", outRefundNo);// 商户退单单号
		map.put("total_fee", totalFee);// 总金额
		map.put("refund_fee", refundFee);// 退款金额
		map.put("op_user_id", PropertiesUtils.getProperties("mch_id"));// 默认为商户号
		/**
		 * 退款渠道，目前2中 ORIGINAL-原路退款，默认BALANCE-余额
		 */
		map.put("refund_channel", refundChannel);// 退款渠道
		map.put("service", "trade.single.refund");
		map.put("version", version);
		map.put("charset", charset);
		map.put("sign_type", sign_type);

		String key = PropertiesUtils.getProperties("key");
		String reqUrl = PropertiesUtils.getProperties("req_url");
		map.put("mch_id", PropertiesUtils.getProperties("mch_id"));
		map.put("nonce_str", String.valueOf(new Date().getTime()));

		Map<String, String> params = SignUtils.paraFilter(map);
		StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
		SignUtils.buildPayParams(buf, params, false);
		String preStr = buf.toString();
		String sign = MD5.sign(preStr, "&key=" + key, "utf-8");
		map.put("sign", sign);
		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		String res = null;
		Map<String, String> resultMap = null;
		try {
			HttpPost httpPost = new HttpPost(reqUrl);
			StringEntity entityParams = new StringEntity(
					XmlUtils.parseXML(map), "utf-8");
			httpPost.setEntity(entityParams);
			httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
			client = HttpClients.createDefault();
			response = client.execute(httpPost);
			if (response != null && response.getEntity() != null) {
				resultMap = XmlUtils.toMap(
						EntityUtils.toByteArray(response.getEntity()), "utf-8");
				res = XmlUtils.toXml(resultMap);

				logger.info("================支付退款请求结果=================" + res);
				if (!SignUtils.checkParam(resultMap, key)) {
					res = "验证签名不通过";
				}
			} else {
				res = "操作失败!";
			}
		} catch (Exception e) {
			res = "操作失败";
		} finally {
			if (response != null) {
				response.close();
			}
			if (client != null) {
				client.close();
			}
		}
		Map<String, String> result = new HashMap<String, String>();
		if (res.startsWith("<")) {
			result.put("status", "200");
			result.put("msg", "操作成功，请在日志文件中查看");
		} else {
			result.put("status", "500");
			result.put("msg", res);
		}
		ObjectMapper om = new ObjectMapper();
		om.setDateFormat(new SimpleDateFormat("yyyyMMddHH:mm:ss"));
		String json = om.writeValueAsString(resultMap);
		logger.info("===================退款接口返回结果=======================" + json);
		return json;
	}

}
